
package com.whosly.mysql.protocol.packet.impl;

import com.whosly.mysql.protocol.MySQLStatusFlag;
import com.whosly.mysql.protocol.jdbc.MySQLMessage;
import com.whosly.mysql.protocol.packet.jdbc.AbstractMySQLPacket;
import com.whosly.mysql.protocol.packet.util.NettyBufferUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;

/**
 *
 * @author fengyang(yueny09@163.com)
 * @date 2023年06月25日 下午10:13
 */
public class EOFPacket extends AbstractMySQLPacket
{
    public static final byte PACKET_EOF_HEADER = (byte) 0xfe;

    /**
     * header
     */
    public byte fieldCount = PACKET_EOF_HEADER;

    // if capabilities & CLIENT_PROTOCOL_41 {...}
    /**
     * Number of warnings. Sent after all data has been sent to the client.
     */
    public int warningCount = 0;
    /**
     * Contains flags like SERVER_MORE_RESULTS_EXISTS, 2
     */
    public int status = MySQLStatusFlag.SERVER_STATUS_AUTOCOMMIT.getValue();;

    @Override
    public void read(byte[] bodyBytes) {
        MySQLMessage mm = new MySQLMessage(bodyBytes);

        readBody(this, mm);
    }

    private static void readBody(EOFPacket eofPacket, MySQLMessage mm) {
        eofPacket.fieldCount = mm.read();

        // if capabilities & CLIENT_PROTOCOL_41 {...}
        eofPacket.warningCount = mm.readUB2();
        eofPacket.status = mm.readUB2();
    }

    public void write(ChannelHandlerContext ctx) {
        int size = calcPacketSize();
        // default init 256,so it can avoid buff extract
        ByteBuf buffer = ctx.alloc().buffer(size);
        NettyBufferUtil.writeUB3(buffer, size);
        buffer.writeByte(getPackId());

        writeBody(buffer);

        ctx.writeAndFlush(buffer);
    }

    @Override
    public ByteBuf writeBuf(ByteBuf buffer) {
        NettyBufferUtil.writeUB3(buffer, buffer.capacity());
        buffer.writeByte(getPackId());

        writeBody(buffer);

        return buffer;
    }

    @Override
    public ByteBuf writeBuf() {
        ByteBuf buffer = Unpooled.buffer(calcPacketSize());

        return writeBuf(buffer);
    }

    private void writeBody(ByteBuf buffer) {
        buffer.writeByte(fieldCount);

        // if capabilities & CLIENT_PROTOCOL_41 {...}
        NettyBufferUtil.writeUB2(buffer, warningCount);
        NettyBufferUtil.writeUB2(buffer, status);
    }

    public boolean hasStatusFlag(long flag) {
        return ((this.status & flag) == flag);
    }

    @Override
    public int calcPacketSize() {
        return 5;// 1+2+2;
    }

    @Override
    public String getPacketInfo() {
        return "MySQL EOF Packet";
    }

    public static EOFPacket of(byte packId){
        EOFPacket p = new EOFPacket();
        p.setPackId(packId);
        p.status = 2;
        p.warningCount = 0;
        return p;
    }

    public static EOFPacket of(final MySQLMessage mm){
        EOFPacket eofPacket = new EOFPacket();
        eofPacket.setArgs(mm.readUB3(), mm.read());

        readBody(eofPacket, mm);

        return eofPacket;
    }
}